#include <graphics.h>
#include <conio.h>
#include "DataStruct.h"
#include <stdlib.h>



void lineArrow(Graph g)
{
	int x1 = g.node.coor[row].x, y1 = g.node.coor[row].y, x2 = g.node.coor[column].x, y2 = g.node.coor[column].y;
	line(x1, y1, x2, y2);
	distancess = sqrt((y1 - y2) * (y1 - y2) + (x1 - x2) * (x1 - x2));
	double tmpx = double(x1 + (x2 - x1) * (1 - (12 * sqrt(3) / 2) / distancess));
	double tmpy = double(y1 + (y2 - y1) * (1 - (12 * sqrt(3) / 2) / distancess));
	if (y1 == y2)
	{
		line(x2, y2, int(tmpx), int(tmpy + 6));
		line(x2, y2, int(tmpx), int(tmpy - 6));
	}
	else
	{
		double k = (double(x2) - double(x1)) / (double(y1) - double(y2));
		double increX = 6 / sqrt(k * k + 1);
		double increY = 6 * k / sqrt(k * k + 1);
		line(x2, y2, int(tmpx + increX), int(tmpy + increY));
		line(x2, y2, int(tmpx - increX), int(tmpy - increY));
	}
}

void Pan(Graph *g, int row, int col) {
	if (row != col) {
		g->edg[row][col] = int(distancess);
		
	}
}

bool StartLine(Graph g)
{
	MOUSEMSG m;
	while (true)
	{
		m = GetMouseMsg();
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN:
			for (int i = 0; i < num; i++)
				if (m.x >= g.node.coor[i].x - 20 && m.x <= g.node.coor[i].x + 20 && m.y >= g.node.coor[i].y - 20 && m.y <= g.node.coor[i].y + 20)
				{
					row = i;
					return true;
				}
			break;
		default:
			break;
		}				
	}
	return false;
}
bool EndLine(Graph &g) 
{
	MOUSEMSG m;
	while (true)
	{
		m = GetMouseMsg();
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN:
			for (int i = 0; i < num; i++)
				if (m.x >= g.node.coor[i].x - 20 && m.x <= g.node.coor[i].x + 20 && m.y >= g.node.coor[i].y - 20 && m.y <= g.node.coor[i].y + 20)
				{
					column = i;
					return true;
				}
			break;
		default:
			break;
		}
	}
	return false;
}


int main() 
{
	initgraph(900, 650);
	setbkcolor(WHITE);
	cleardevice();
	Graph g;
	int Htext = 30;//字体大小
	char s[10];
	setcolor(RED);
	outtextxy(0, 0, "绘图区域");
	rectangle(-10, -10, 600, 500);
	setbkmode(TRANSPARENT);
	settextstyle(Htext, 0, "华文楷体");
	outtextxy(610, 0, "地标个数：");
	Sleep(1000);
	InputBox(s, 10, "请输入数量");
	outtextxy(610,  Htext, s);
	outtextxy(610, Htext * 2, "地标名称：");
	num = atoi(s);
	
	////////////////////////分配内存
	g.node.a = new char* [num];
	for (int j = 0; j < num; j++)
	{
		g.node.a[j] = new char[50];
	}

	g.node.coor = new Coor[num];

	g.edg = new double* [num];
	for (int j = 0; j < num; j++)
	{
		g.edg[j] = new double[num];
	}
	/////////////////////////////////

	CreateGraph(&g);//初始化

	//////////////输入相关信息
	for (int j = 0; j < num; j++)
	{
		InputBox(g.node.a[j], 10, "请输入地标名");
		outtextxy(610, Htext*(j+3), g.node.a[j]);
	}
	char startdi[50],endi[50];
	outtextxy(0, 510, "起始地："); InputBox(startdi, 50, "请输入地标名"); outtextxy(textwidth("起始地：")+20, 510, startdi);
	outtextxy(0, 550, "目的地："); InputBox(endi, 50, "请输入地标名"); outtextxy(textwidth("起始地：") + 20, 550, endi);
	///////////////////////////////

	//画点
	setcolor(GREEN);
	bool flag = false; int i = 0; char val;
	MOUSEMSG m;		// 定义鼠标消息
	while (true)
	{
		// 获取一条鼠标消息
		m = GetMouseMsg();
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN:
			if (flag == false&&m.x<600-20&&m.y<500-20&&m.x>20&&m.y>20) {
				fillcircle(m.x, m.y, 20);
				
				outtextxy(m.x, m.y, g.node.a[i]);
				g.node.coor[i].x = m.x;
				g.node.coor[i].y = m.y;
				i++;
			}
			break;
		case WM_LBUTTONUP:
			if (flag)
				flag = !flag;
			break;
		}
		
		if (i == num)
			break;
	}
	
	//画线
	setcolor(BLUE);
	while (true)
	{
		StartLine(g);
		EndLine(g);
		lineArrow(g);
		sprintf(num_dist, "%d", int(distancess));
		outtextxy((g.node.coor[row].x + g.node.coor[column].x) / 2, (g.node.coor[row].y + g.node.coor[column].y) / 2, num_dist);
		Pan(&g, row, column);
		if (_kbhit())
		{
			val = getch();
			if (val == 27)
				break;
		}	
	}

	//计算最短路径
	Dijkstra(g);
	//输出
	setcolor(RED);
	outtextxy(0, 590, "最短距离为：");
	sprintf(num_dist, "%d", dis(g, startdi, endi));
	outtextxy(textwidth("最短距离为：") + 20, 590, num_dist);

	//释放
	for (int i = 0; i < num; i++)
		delete[]g.node.a[i];
	delete[]g.node.a;
	delete[]g.node.coor;
	for (int i = 0; i < num; i++)
		delete[]g.edg[i];
	delete[]g.edg;
	for (int i = 0; i < num; i++)
		delete[]distances[i];
	delete[]distances;
	/////////////////
	_getch();
	closegraph();

	return 0;
}